home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 08 - 1992 / 08.03 Jul 92 / Matrix Parser / Inverse < prev    next >
Encoding:
Text File  |  1992-12-24  |  6.2 KB  |  332 lines  |  [TEXT/PJMM]

  1. unit Inverse;
  2.  
  3.  
  4. interface
  5.  
  6.     uses
  7.         Globals;
  8.  
  9.  
  10.     procedure Inverse (var matrix: hdlsinglearraymatrix; var mrows, ncols: longint; var error: str255);
  11.  
  12.  
  13. implementation
  14.  
  15.  
  16.     procedure Inverse;
  17.  
  18.         label
  19.             997, 999;
  20.  
  21.         const
  22.             thresh = 0.00000001;
  23.             np = 30000;
  24.  
  25.         type
  26.  
  27.             nparray = array[1..np] of extended;
  28.             ptrnparray = ^nparray;
  29.             hdlnparray = ^ptrnparray;
  30.  
  31.             narray = array[1..np] of extended;
  32.             ptrnarray = ^narray;
  33.             hdlnarray = ^ptrnarray;
  34.  
  35.             iarray = array[1..np] of longint;
  36.             ptriarray = ^iarray;
  37.             hdliarray = ^ptriarray;
  38.  
  39.         var
  40.             i, j, k, l, m, n, mm, nn: longint;
  41.             amat, vmat: hdlsinglearraymatrix;
  42.             sum, wmax, wmin, d, x: extended;
  43.             a, y: hdlnparray;
  44.             b: hdlnarray;
  45.             indx: hdliarray;
  46.             amatnew, vmatnew, wnew: boolean;
  47.  
  48.         procedure ludcmp (var a: hdlnparray; n, np: longint; var indx: hdliarray; var d: extended);
  49.  
  50.  {in the main routine.}
  51.  
  52.             const
  53.                 tiny = 1.0e-20;
  54.  
  55.             var
  56.                 k, j, imax, i: longint;
  57.                 sum, dum, big: extended;
  58.                 vv: hdlnarray;
  59.  
  60.         begin
  61.  
  62.             amatnew := false;
  63.             vmatnew := false;
  64.             wnew := false;
  65.  
  66.             blocksize := n * 10;
  67.  
  68.             vv := hdlnarray(NewHandle(blocksize));
  69.  
  70.             d := 1.0;
  71.             for i := 1 to n do
  72.                 begin
  73.                     big := 0.0;
  74.  
  75.                     for j := 1 to n do
  76.                         if (abs(a^^[(i - 1) * n + j]) > big) then
  77.                             big := abs(a^^[(i - 1) * n + j]);
  78.                     if (big = 0.0) then
  79.                         begin
  80.                             writeln('pause in ludcmp - singular matrix');
  81.                             readln
  82.                         end;
  83.  
  84.                     vv^^[i] := 1.0 / big
  85.                 end;
  86.             for j := 1 to n do
  87.                 begin
  88.                     if (j > 1) then
  89.                         begin
  90.                             for i := 1 to j - 1 do
  91.                                 begin
  92.                                     sum := a^^[(i - 1) * n + j];
  93.                                     if (i > 1) then
  94.                                         begin
  95.                                             for k := 1 to i - 1 do
  96.                                                 begin
  97.                                                     sum := sum - a^^[(i - 1) * n + k] * a^^[(k - 1) * n + j]
  98.                                                 end;
  99.                                             a^^[(i - 1) * n + j] := sum
  100.                                         end
  101.                                 end
  102.                         end;
  103.  
  104.                     big := 0.0;
  105.                     for i := j to n do
  106.                         begin
  107.                             sum := a^^[(i - 1) * n + j];
  108.                             if (j > 1) then
  109.                                 begin
  110.                                     for k := 1 to j - 1 do
  111.                                         begin
  112.                                             sum := sum - a^^[(i - 1) * n + k] * a^^[(k - 1) * n + j]
  113.                                         end;
  114.                                     a^^[(i - 1) * n + j] := sum
  115.                                 end;
  116.                             dum := vv^^[i] * abs(sum);
  117.                             if (dum > big) then
  118.                                 begin
  119.                                     big := dum;
  120.                                     imax := i
  121.                                 end
  122.                         end;
  123.                     if (j <> imax) then
  124.                         begin
  125.                             for k := 1 to n do
  126.                                 begin
  127.                                     dum := a^^[(imax - 1) * n + k];
  128.                                     a^^[(imax - 1) * n + k] := a^^[(j - 1) * n + k];
  129.                                     a^^[(j - 1) * n + k] := dum
  130.                                 end;
  131.                             d := -d;
  132.                             vv^^[imax] := vv^^[j]
  133.                         end;
  134.                     indx^^[j] := imax;
  135.                     if (j <> n) then
  136.                         begin
  137.                             if (a^^[(j - 1) * n + j] = 0.0) then
  138.                                 a^^[(j - 1) * n + j] := tiny;
  139.                             dum := 1.0 / a^^[(j - 1) * n + j];
  140.                             for i := j + 1 to n do
  141.                                 begin
  142.                                     a^^[(i - 1) * n + j] := a^^[(i - 1) * n + j] * dum
  143.                                 end
  144.                         end
  145.                 end;
  146.             if (a^^[n * n] = 0.0) then
  147.                 a^^[n * n] := tiny;
  148.  
  149.             DisposHandle(handle(vv));
  150.  
  151.         end;
  152.  
  153.  
  154.         procedure lubksb (a: hdlnparray; n, np: longint; indx: hdliarray; var b: hdlnarray);
  155.  
  156. {  * Programs  using lubksb must define the types }
  157.  
  158. {in the main routine *}
  159.  
  160.             var
  161.                 j, ip, ii, i: longint;
  162.                 sum: extended;
  163.  
  164.         begin
  165.             ii := 0;
  166.             for i := 1 to n do
  167.                 begin
  168.                     ip := indx^^[i];
  169.                     sum := b^^[ip];
  170.                     b^^[ip] := b^^[i];
  171.                     if (ii <> 0) then
  172.                         begin
  173.                             for j := ii to i - 1 do
  174.                                 begin
  175.                                     sum := sum - a^^[(i - 1) * n + j] * b^^[j]
  176.                                 end
  177.                         end
  178.                     else if (sum <> 0.0) then
  179.                         begin
  180.                             ii := i
  181.                         end;
  182.                     b^^[i] := sum
  183.                 end;
  184.             for i := n downto 1 do
  185.                 begin
  186.                     sum := b^^[i];
  187.                     if (i < n) then
  188.                         begin
  189.                             for j := i + 1 to n do
  190.                                 begin
  191.                                     sum := sum - a^^[(i - 1) * n + j] * b^^[j]
  192.                                 end
  193.                         end;
  194.                     b^^[i] := sum / a^^[(i - 1) * n + i]
  195.                 end
  196.         end;
  197.  
  198.     begin
  199.  
  200.         m := mrows;
  201.         n := ncols;
  202.  
  203.         blocksize := 10 * n * n;
  204.         a := hdlnparray(NewHandle(blocksize));
  205.         y := hdlnparray(NewHandle(blocksize));
  206.  
  207.         blocksize := 10 * n;
  208.         b := hdlnarray(NewHandle(blocksize));
  209.         indx := hdliarray(NewHandle(blocksize));
  210.  
  211.         if m < n then
  212.             begin
  213.                 error := 'Ill conditioned matrix. Number of rows less than number of columns';
  214.                 goto 999;
  215.             end;
  216.  
  217.         if m > n then
  218.             begin
  219.                 l := 0;
  220.                 for i := 1 to n do
  221.                     for j := 1 to n do
  222.                         begin
  223.                             sum := 0;
  224.                             for k := 1 to m do
  225.                                 begin
  226.                                     sum := sum + matrix^^[(k - 1) * n + i + 2] * matrix^^[(k - 1) * n + j + 2];
  227.                                 end;
  228.                             l := l + 1;
  229.                             a^^[l] := sum;
  230.                         end;
  231.                 blocksize := 10 * m * n;
  232.                 vmat := hdlsinglearraymatrix(NewHandle(blocksize));
  233.                 for l := 1 to m * n do
  234.                     begin
  235.                         x := matrix^^[l + 2];
  236.                         vmat^^[l] := x;
  237.                     end;
  238.                 goto 997
  239.             end;
  240.  
  241.  
  242.         if m = n then
  243.             begin
  244.                 for l := 1 to m * n do
  245.                     begin
  246.                         x := matrix^^[l + 2];
  247.                         a^^[l] := x;
  248.                     end;
  249.             end;
  250.  
  251.  
  252. 997:
  253.         ludcmp(a, n, np, indx, d);
  254.         for j := 1 to n do
  255.             d := d * a^^[(j - 1) * n + j];
  256.  
  257.         if abs(d) > thresh then
  258.             begin
  259.  
  260.                 for i := 1 to n do
  261.                     begin
  262.                         for j := 1 to n do
  263.                             begin
  264.                                 b^^[j] := 0;
  265.                                 if j = i then
  266.                                     b^^[j] := 1;
  267.                             end;
  268.                         lubksb(a, n, np, indx, b);
  269.                         for j := 1 to n do
  270.                             y^^[(j - 1) * n + i] := b^^[j];
  271.                     end;
  272.  
  273.                 if m = n then
  274.                     begin
  275.                         begin
  276.  
  277.                             matrix^^[1] := n;
  278.                             matrix^^[2] := n;
  279.                             for i := 1 to n * n do
  280.                                 begin
  281.                                     x := y^^[i];
  282.                                     matrix^^[i + 2] := x;
  283.                                 end;
  284.                             goto 999;
  285.                         end;
  286.                     end;
  287.  
  288.                 if m > n then
  289.                     begin
  290.  
  291.                         blocksize := 10 * n * n;
  292.                         amat := hdlsinglearraymatrix(NewHandle(blocksize));
  293.  
  294.                         for i := 1 to n * n do
  295.                             begin
  296.                                 x := y^^[i];
  297.                                 amat^^[i] := x;
  298.                             end;
  299.  
  300.                         matrix^^[1] := n;
  301.                         matrix^^[2] := m;
  302.  
  303.                         l := 2;
  304.                         for i := 1 to n do
  305.                             for j := 1 to m do
  306.                                 begin
  307.                                     sum := 0;
  308.                                     for k := 1 to n do
  309.                                         begin
  310.                                             mm := (i - 1) * n + k;
  311.                                             nn := (j - 1) * n + k;
  312.                                             sum := sum + amat^^[mm] * vmat^^[nn];
  313.                                         end;
  314.                                     l := l + 1;
  315.                                     matrix^^[l] := sum;
  316.                                 end;
  317.                         DisposHandle(handle(amat));
  318.                         DisposHandle(handle(vmat));
  319.  
  320.                         goto 999;
  321.                     end;
  322.  
  323.             end;
  324.  
  325. 999:
  326.         DisposHandle(handle(a));
  327.         DisposHandle(handle(y));
  328.         DisposHandle(handle(indx));
  329.  
  330.     end;
  331.  
  332. end.